/*
 * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xuidemo.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.view.ViewCompat;

import com.xuexiang.xui.utils.DensityUtils;
import com.xuexiang.xuidemo.fragment.diandiandian.OneTouch;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class FingerTouch extends View {
    private List<OneTouch> touches = new ArrayList<>();
    private OneTouch selected = null;
    private Paint mPaint;
    private float RADIUS = DensityUtils.dp2px(getContext(),70);
    private float multiple = 1f;
    private boolean selecting = false;
    ValueAnimator valueAnimator;

    private int[] colors = {
            Color.parseColor("#6739b6"), Color.parseColor("#9c26b0"),
            Color.parseColor("#e54d42"), Color.parseColor("#f58220"),
            Color.parseColor("#494e8f"), Color.parseColor("#1d953f"),
            Color.parseColor("#f26522"), Color.parseColor("#fcaf17"),
            Color.parseColor("#ffc20e"), Color.parseColor("#33a3dc")
    };

    public FingerTouch(Context context) {
        super(context);
    }

    public FingerTouch(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public FingerTouch(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public FingerTouch(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAlpha(255);
        for(int i = 0; i < touches.size(); i++) {
            OneTouch touch = touches.get(i);
            mPaint.setColor(touch.color);
            canvas.drawCircle(touch.x, touch.y, RADIUS*multiple, mPaint);
        }
        if(selected != null) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.parseColor("#ef5b9c"));
            paint.setStyle(Paint.Style.STROKE);
            DashPathEffect effects = new DashPathEffect(new float[]{10,5},1);
            paint.setPathEffect(effects);
            paint.setStrokeWidth(DensityUtils.dp2px(getContext(),10));
            canvas.drawCircle(selected.x, selected.y, RADIUS*1.2f, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int actionIndex = event.getActionIndex();
        int pointerId = event.getPointerId(actionIndex);
        int actionType = event.getActionMasked();
        int x, y;
        Iterator<OneTouch> iterator = touches.iterator();
        switch (actionType) {
            case MotionEvent.ACTION_DOWN:
                Log.i("FingerTouch", "ACTION_DOWN");
                x = (int) event.getX(actionIndex);
                y = (int) event.getY(actionIndex);
                touches.add(new OneTouch(x, y, pointerId, colors[pointerId%10]));
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                Log.i("FingerTouch", "ACTION_POINTER_DOWN");
                x = (int) event.getX(actionIndex);
                y = (int) event.getY(actionIndex);
                touches.add(new OneTouch(x, y, pointerId, colors[pointerId%10]));
                break;
            case MotionEvent.ACTION_UP:
                Log.i("FingerTouch", "ACTION_UP");
                touches.clear();
                selected = null;
                if(valueAnimator != null && valueAnimator.isRunning()) {
                    valueAnimator.cancel();
                    multiple = 1f;
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                Log.i("FingerTouch", "ACTION_POINTER_UP");
                while(iterator.hasNext()) {
                    OneTouch touch = iterator.next();
                    if(touch.id == pointerId) {
                        if(selected == touch) selected = null;
                        iterator.remove();
                        break;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("FingerTouch", "ACTION_MOVE pointerId:"+pointerId);
                while(iterator.hasNext()) {
                    OneTouch touch = iterator.next();
                    int index = event.findPointerIndex(touch.id);
                    touch.x = (int) event.getX(index);
                    touch.y = (int) event.getY(index);
                }
                break;
        }
        invalidate();
        return true;
    }

    public void Flash() {
        valueAnimator = ValueAnimator.ofFloat(1f, 1.25f, 1f, 1.25f, 1f, 1.25f, 1f, 1.25f, 1f, 1.25f, 1f);
        valueAnimator.setDuration(5000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float mul = (float) valueAnimator.getAnimatedValue();
                multiple = mul;
                ViewCompat.postInvalidateOnAnimation(FingerTouch.this);
            }
        });
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                if(touches.size() > 0) {
                    int rand = (int) (Math.random() * 17) % touches.size();
                    selected = touches.get(rand);
                }
                selecting = false;
            }
        });
        valueAnimator.start();
    }

    public void Select() {
        if(selecting || touches.isEmpty()) return;
        selecting = true;
        selected = null;
        Flash();
    }
}
